package com.zx.练习题._2022面试题;

import com.zx.common.util.ThreadUtil;
import java.util.LinkedHashMap;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class 接口调用次数统计 {

    private static volatile LinkedHashMap<Long, AtomicInteger> COUNTER = new LinkedHashMap<>(16, 0.75F, true);
    private static Random r = new Random();
    private static ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock();

    public static void main(String[] args) {
        //开启看门狗
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        executor.scheduleAtFixedRate(() -> {
            Long curr = getCurr();
            // 移除超过5s的数据
            if (COUNTER.size() > 5) {
                LOCK.writeLock().lock();
                try {
                    Long key = COUNTER.entrySet().iterator().next().getKey();
                    if (key + 4 < curr) {
                        COUNTER.remove(key);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    LOCK.writeLock().unlock();
                }
            }

            LOCK.readLock().lock();
            try {
                Integer reduce = COUNTER.values().stream().map(AtomicInteger::get).reduce(0, Integer::sum);
                // 统计数据
                System.out.print("sum=" + reduce + ",");
                System.out.println(COUNTER.toString());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                LOCK.readLock().unlock();
            }
        }, 1, 1, TimeUnit.SECONDS);

        //模拟调用
        ThreadPoolExecutor callPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(200);
        for (int i = 0; i < callPool.getCorePoolSize(); i++) {
            callPool.execute(() -> {
                for (int j = 0; j < 1000; j++) {
                    call();
                    ThreadUtil.sleepMill(200);
                }
            });
        }
        callPool.shutdown();
    }

    private static void call() {
        counter();
        try {
            //Thread.sleep(r.nextInt(3000));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void counter() {
        Long curr = getCurr();
        AtomicInteger c = COUNTER.get(curr);

        if (c == null) {
            LOCK.writeLock().lock();//缩小锁的范围
            try {
                c = COUNTER.get(curr);
                // double check
                if (c == null) {
                    c = new AtomicInteger(1);
                    COUNTER.put(curr, c);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                LOCK.writeLock().unlock();
            }
        }
        c.incrementAndGet();
    }


    private static Long getCurr() {
        return System.currentTimeMillis() / 1000;
    }

}
